<!DOCTYPE html>


<html lang="zh-CN">
  

    <head>
      <meta charset="utf-8" />
        
      <meta name="description" content="这个人很懒，什么都没留下" />
      
      <meta
        name="viewport"
        content="width=device-width, initial-scale=1, maximum-scale=1"
      />
      <title> DJ Hong&#39;s BLOG</title>
  <meta name="generator" content="hexo-theme-ayer">
      
      <link rel="shortcut icon" href="/favicon.jpg" />
       
<link rel="stylesheet" href="/dist/main.css">

      <link
        rel="stylesheet"
        href="https://cdn.jsdelivr.net/gh/Shen-Yu/cdn/css/remixicon.min.css"
      />
      
<link rel="stylesheet" href="/css/custom.css">
 
      <script src="https://cdn.jsdelivr.net/npm/pace-js@1.0.2/pace.min.js"></script>
       
 

      <link
        rel="stylesheet"
        href="https://cdn.jsdelivr.net/npm/@sweetalert2/theme-bulma@5.0.1/bulma.min.css"
      />
      <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.0.19/dist/sweetalert2.min.js"></script>

      <!-- mermaid -->
      
      <style>
        .swal2-styled.swal2-confirm {
          font-size: 1.6rem;
        }
      </style>
    <link rel="alternate" href="/atom.xml" title="DJ Hong's BLOG" type="application/atom+xml">
</head>
  </html>
</html>


<body>
  <div id="app">
    
      
    <main class="content on">
      



<!-- Subtitle -->

<div id="main">
  <section class="outer">
  
  
  <article class="articles">
    
    
    
    
    <article
  id="post-2019年8月读书心得"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2019/08/26/2019%E5%B9%B48%E6%9C%88%E8%AF%BB%E4%B9%A6%E5%BF%83%E5%BE%97/"
    >2019年8月读书心得</a> 
</h2>
 

      
    </header>
     
    <div class="article-meta">
      <a href="/2019/08/26/2019%E5%B9%B48%E6%9C%88%E8%AF%BB%E4%B9%A6%E5%BF%83%E5%BE%97/" class="article-date">
  <time datetime="2019-08-26T08:02:45.000Z" itemprop="datePublished">2019-08-26</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/%E9%98%85%E8%AF%BB/">阅读</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <p>距离上一次读书大约有2年了吧~那会儿花了一个月的时间读完了挺厚的两本《基督山伯爵》。阅读给人带来的最直接的好处是，可以让心静下来，遇事莫急，先过过脑，思考思考，在做决策。</p>
<p>由于种种原因吧。重新拾起阅读这个习惯选择的第一本书，是来自华为CEO任正非先生桌头的《美国陷阱》</p>
<p><img src="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/2019%E5%B9%B48%E6%9C%88%E8%AF%BB%E4%B9%A6%E5%BF%83%E5%BE%97/2019%E5%B9%B48%E6%9C%88%E8%AF%BB%E4%B9%A6%E5%BF%83%E5%BE%971.jpg"><br><img src="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/2019%E5%B9%B48%E6%9C%88%E8%AF%BB%E4%B9%A6%E5%BF%83%E5%BE%97/2019%E5%B9%B48%E6%9C%88%E8%AF%BB%E4%B9%A6%E5%BF%83%E5%BE%972.jpg"></p>
<p>本书以作者弗雷德里克·皮耶鲁齐的亲身经历为依据，描述了美国利用其强大的国力“强制”实时其“长臂管辖”能力以实现其自身目的。</p>
<p>从书中的描写，我们可以看出，作者是这场隐蔽的经济战争的牺牲品、替罪羊。在他入狱之后，先后被自己的公司（法国阿尔斯通）所出卖，被自己的国家所遗忘。公司里的高管，人人只管着自保，而作者的祖国——法国，在政治上也没有任何可以谈判的筹码，只能忍气吞声。最终，阿尔斯通的CEO柏克龙以公司为筹码换取自身平安，将法国的“明珠”产业——阿尔斯通的电力产业，卖给了美国通用电气公司。</p>
<p>他们是如何做到的呢？</p>
<p>美国政府自认为有权追诉任何一家公司，只要它用美元计价签订合同，或者仅仅通过设在美国的服务器（如谷歌邮箱或微软邮箱）收发、存储（甚至只是过境）邮件，这些都被视为国际贸易工具。这就是美国人的一个把戏，他们把一项可能削弱自身企业的法律转变为干涉他国企业、发动经济战的神奇工具。<br>而到手的“罪犯”不需要是真正的幕后主使，只要美国政府愿意，那他就是。只要能达到他们的狼子野心，就可以了。</p>
<p>看完这本书，我又去查阅了“孟晚舟事件”，结果和我想的一样，这是美国故技重施的阴谋，想要通过相同的手法，对在通信领域有着举足轻重地位的中国公司“华为”入手。<br>略有不同的是，我们国家对此事高度关注，华为公司也在积极应对。</p>
<p>说到这里，忍不住想提一下中美的贸易战。作为一名普通老百姓，可能对贸易战的直观感受就是…没啥感觉，成天看新闻说贸易战，然后各种东西的涨价不知道和贸易战是否有关。不管我们相不相信，愿不愿意，这场经济战争，都已经打响了。我觉得我所能做的，就是相信我们的国家，能够在这场战斗中展现出我们的优势和强大国力。这里有一篇<br><a target="_blank" rel="noopener" href="https://media.weibo.cn/article?id=2309404404008738488342">《2019年8月中美贸易战简况总结》</a>，个人觉得还是非常值得一读的。我们承认美国拥有世界上首屈一指的国力，但是如今的中国在世界上，也是有着举足轻重的力量。</p>
<p>最后提一下。</p>
<p>《美国陷阱》这本书的前29节，我看的是实体书。我并没有购买这本书。而是在支付宝的“浙江图书馆”借阅了这本书。并且它支持邮寄（邮政+京东），到手速度非常快。<br>而后面的章节，由于出差没有带书。在某读书软件中读完了剩余的内容。感觉电子书阅读，其实也是蛮能接受的，方便随时阅读，就是看久了屏幕，眼睛有点吃力。</p>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/%E8%AF%BB%E4%B9%A6%E5%BF%83%E5%BE%97/" rel="tag">读书心得</a></li></ul>

    </footer>
  </div>

    
 
    
</article>

    
    <article
  id="post-iOS源码阅读——YYWebImage"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2018/12/25/iOS%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB%E2%80%94%E2%80%94YYWebImage/"
    >iOS源码阅读——YYWebImage</a> 
</h2>
 

      
    </header>
     
    <div class="article-meta">
      <a href="/2018/12/25/iOS%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB%E2%80%94%E2%80%94YYWebImage/" class="article-date">
  <time datetime="2018-12-25T12:07:29.000Z" itemprop="datePublished">2018-12-25</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/iOS/">iOS</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <p>加载网络图片是项目中比较常见的需求，<code>YYWebImage</code>是Github中比较好用的图片加载开源框架之一。<code>YYWebImage</code>是作者为UIImageView创建的Category，使得UIImageView的实例能够直接调用一个实例方法，就能获取网络图片的功能。</p>
<h2 id="UIImageView-YYWebImage的实例方法"><a href="#UIImageView-YYWebImage的实例方法" class="headerlink" title="UIImageView+YYWebImage的实例方法"></a>UIImageView+YYWebImage的实例方法</h2><p>在<code>UIImageView+YYWebImage</code>列举了5中方法供开发者使用，分别是：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">①- (void)yy_setImageWithURL:(nullable NSURL *)imageURL placeholder:(nullable UIImage *)placeholder;</span><br><span class="line">②- (void)yy_setImageWithURL:(nullable NSURL *)imageURL options:(YYWebImageOptions)options;</span><br><span class="line">③- (void)yy_setImageWithURL:(nullable NSURL *)imageURL</span><br><span class="line">               placeholder:(nullable UIImage *)placeholder</span><br><span class="line">                   options:(YYWebImageOptions)options</span><br><span class="line">                completion:(nullable YYWebImageCompletionBlock)completion;</span><br><span class="line">④- (void)yy_setImageWithURL:(nullable NSURL *)imageURL</span><br><span class="line">               placeholder:(nullable UIImage *)placeholder</span><br><span class="line">                   options:(YYWebImageOptions)options</span><br><span class="line">                  progress:(nullable YYWebImageProgressBlock)progress</span><br><span class="line">                 transform:(nullable YYWebImageTransformBlock)transform</span><br><span class="line">                completion:(nullable YYWebImageCompletionBlock)completion;</span><br><span class="line"></span><br><span class="line">⑤- (void)yy_setHighlightedImageWithURL:(NSURL *)imageURL</span><br><span class="line">                          placeholder:(UIImage *)placeholder</span><br><span class="line">                              options:(YYWebImageOptions)options</span><br><span class="line">                              manager:(YYWebImageManager *)manager</span><br><span class="line">                             progress:(YYWebImageProgressBlock)progress</span><br><span class="line">                            transform:(YYWebImageTransformBlock)transform</span><br><span class="line">                           completion:(YYWebImageCompletionBlock)completion;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>从方法的具体实现中可以看到，①~④的方法实现，都是调用了方法⑤，只是参数传递有所不同。所以我们只需要着重阅读方法⑤的代码实现</p>
<h2 id="具体实现——UIImageView-YYWebImage-m"><a href="#具体实现——UIImageView-YYWebImage-m" class="headerlink" title="具体实现——UIImageView+YYWebImage.m"></a>具体实现——<a target="_blank" rel="noopener" href="https://github.com/ibireme/YYWebImage/blob/master/YYWebImage/Categories/UIImageView%2BYYWebImage.m">UIImageView+YYWebImage.m</a></h2><ol>
<li><p>判断传入的图片链接如果是NSString类型的实例，要先转换为NSURL类型的实例</p>
</li>
<li><p>三目运算，判断<code>YYWebImageManager</code>实例初始化与否，确保初始化完成</p>
</li>
<li><p>_YYWebImageSetter</p>
<ol>
<li>关于<code>_YYWebImageSetter</code>，作者的注解是：Private class used by web image categories.Typically, you should not use this class directly.它是Web图像类别使用的私有类。通常，您不应直接使用此类。</li>
<li>包含2个只读属性、和4个方法<ol>
<li>属性：（NSURL*）imageURL、(int32_t) sentinel</li>
<li>方法：<ol>
<li>-(int32_t)setOperationWithSentinel: url: options: manager: progress: transform: completion:</li>
<li>-(int32_t)cancel</li>
<li>-(int32_t)cancelWithNewURL:</li>
<li>+(dispatch_queue_t)setterQueue</li>
</ol>
</li>
<li><code>objc_getAssociatedObject</code>：通过runtime获取UIImageView的动态属性setter，类型为<code>_YYWebImageSetter</code>。</li>
<li>如果获取到的setter为空，则需要新建一个_YYWebImageSetter实例，并动态关联这个属性。</li>
<li>[setter cancelWithNewURL:imageURL]通过新的图片链接，取消原来的线程操作。实现步骤：<ol>
<li>dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER)如果_lock的信号量值为0，则线程阻塞，不往下执行。否则，信号量-1（初始信号量为1），继续往下执行。</li>
<li>判断 _operation线程是否存在，如果存在，取消这个线程，并置空。</li>
<li>为 _imageURL变量赋值——新的图片连接</li>
<li>sentinel = OSAtomicIncrement32(&amp;_sentinel);值自增</li>
<li>dispatch_semaphore_signal(_lock) 信号量+1</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
<li><p>_yy_dispatch_sync_on_main_queue确保在主线程执行后面的代码。</p>
<ol>
<li>从内存缓存<code>YYImageCacheTypeMemory</code>中获取图片，如果获取成功，则执行complete()，结束操作。</li>
<li>未在内存缓存中获取到图片，继续执行。<ol>
<li>通过 [_YYWebImageSetter setterQueue]，获取到一个与全局队列优先级相同的队列，并异步执行后面的代码</li>
<li>预先创建和实现的  YYWebImageCompletionBlock _completion block。</li>
<li>实现 _YYWebImageSetter *setter的实例方法—— [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]。</li>
<li>通过一路追随 _completion block的传递，发现进入了  YYWebImageOperation  类。</li>
<li>YYWebImageOperation继承于 NSOperation。作者重写了NSOpration类的start，方法。并在恰当时机调用了自定义方法 _startOperation。</li>
<li>_startOperation方法的实现<ol>
<li>当_cache存在且用户没有设置  YYWebImageOptionUseNSURLCache 和  YYWebImageOptionRefreshImageCache 选项。会先去取图片缓存。</li>
<li>获取内存图片缓存，调用方法 [_cache getImageForKey:_cacheKey withType:YYImageCacheTypeMemory];。通过_cacheKey获取内存缓存。如果获取成功，结束后台线程；获取失败，则向下执行</li>
<li>当用户没有设置忽略磁盘缓存 YYWebImageOptionIgnoreDiskCache，则接下去，从磁盘获取图片缓存。</li>
<li>获取磁盘图片缓存，调用方法 [self.cache getImageForKey:self.cacheKey withType:YYImageCacheTypeDisk]。<ol>
<li>如果从磁盘获取图片缓存成功，先将图片缓存到内存，并调用 _didReceiveImageFromDiskCache方法。</li>
<li>如果同磁盘获取图片缓存失败，则需要从网络请求图片数据。</li>
</ol>
</li>
<li>通过网络请求获取图片。<ol>
<li>通过 incrementNetworkActivityCount为请求数量+1</li>
<li>通过 connection: didReceiveData: 方法的回调，不断地获取数据。</li>
<li>在 connectionDidFinishLoading 的方法回调中，调用 _didReceiveImageFromWeb 方法。</li>
<li>通过 decrementNetworkActivityCount 为请求数量-1</li>
</ol>
</li>
<li><ol>
<li>_didReceiveImageFromWeb成功从网络获取图片。将图片分别存入内存和磁盘缓存中。</li>
</ol>
</li>
<li>回到之前实现的 _completion代码块。主要是一些动画特效。</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
<li><p>通过<code>completion:(nullable YYWebImageCompletionBlock)completion</code>，将结果返回给开发者</p>
</li>
</ol>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p><code>YYWebImage</code>的实现合乎我们的直觉：</p>
<ul>
<li>查看缓存（1.内存；2.磁盘）<ul>
<li>缓存命中<ul>
<li>返回图片</li>
<li>更新视图</li>
</ul>
</li>
<li>缓存未命中<ul>
<li>异步下载图片</li>
<li>加入缓存</li>
<li>更新视图</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="心得"><a href="#心得" class="headerlink" title="心得"></a>心得</h3><p>之前尝试阅读过<code>YYWebImage</code>框架，当时的方法是一个类一个类看，从.h的属性、方法，到.m的具体实现。说实话，看起来着实有点烧脑和低效。读了<a target="_blank" rel="noopener" href="https://github.com/draveness/analyze">Draven</a>的《<a target="_blank" rel="noopener" href="https://github.com/draveness/analyze/blob/master/contents/SDWebImage/iOS%20%E6%BA%90%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%90%20---%20SDWebImage.md">iOS 源代码分析 — SDWebImage</a>》，有所启发，直接以API作为入口阅读源码，更具方向性，才会更有收获。<br>文章中涉及到了<a target="_blank" rel="noopener" href="https://www.cnblogs.com/snailHL/p/3906112.html">dispatch_semaphore</a>、<a target="_blank" rel="noopener" href="https://www.jianshu.com/p/8f07a9bdd1cd">队列优先级</a>的知识。</p>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/YYWebImage/" rel="tag">YYWebImage</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB/" rel="tag">源码阅读</a></li></ul>

    </footer>
  </div>

    
 
    
</article>

    
    <article
  id="post-iOS-UITableView-长按移动Cell的位置"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2018/11/30/iOS-UITableView-%E9%95%BF%E6%8C%89%E7%A7%BB%E5%8A%A8Cell%E7%9A%84%E4%BD%8D%E7%BD%AE/"
    >iOS UITableView 长按移动Cell的位置</a> 
</h2>
 

      
    </header>
     
    <div class="article-meta">
      <a href="/2018/11/30/iOS-UITableView-%E9%95%BF%E6%8C%89%E7%A7%BB%E5%8A%A8Cell%E7%9A%84%E4%BD%8D%E7%BD%AE/" class="article-date">
  <time datetime="2018-11-30T11:49:23.000Z" itemprop="datePublished">2018-11-30</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/iOS/">iOS</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <h3 id="实现思路："><a href="#实现思路：" class="headerlink" title="实现思路："></a>实现思路：</h3><ol>
<li>长按获取当前手指所在位置的indexPath</li>
<li>通过indexPath获取对应cell，并生成快照</li>
<li>移动。<br>3.1. 快照跟随手指移动<br>3.2. 当手指移动到其他cell的位置时，执行位置互换，和数据互换</li>
<li>放开手指，移除快照</li>
</ol>
<br />

<h3 id="实现步骤："><a href="#实现步骤：" class="headerlink" title="实现步骤："></a>实现步骤：</h3><p>准备：(UITableView*)tableView，数据源(NSMutableArray*)lists</p>
<h5 id="第一步：为tableView添加长按手势"><a href="#第一步：为tableView添加长按手势" class="headerlink" title="第一步：为tableView添加长按手势"></a>第一步：为tableView添加长按手势</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">UILongPressGestureRecognizer* longRec = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];</span><br><span class="line">[_tableView addGestureRecognizer:longRec];</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h5 id="第二步：实现手势对应的操作。"><a href="#第二步：实现手势对应的操作。" class="headerlink" title="第二步：实现手势对应的操作。"></a>第二步：实现手势对应的操作。</h5><p>① <code>UIGestureRecognizerStateBegan</code> 时，选中cell。<br>通过手势在tableView的location，可以获取到tableView上对应的IndexPath，从而也能获取到对应的cell。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">//UIGestureRecognizer 的实例方法，可获取手势在载体上的点坐标</span><br><span class="line">- (CGPoint)locationInView:(nullable UIView*)view;</span><br><span class="line"></span><br><span class="line">//UITableView 的实例方法，可获取屏幕上某个点下存在的indexPath</span><br><span class="line">- (nullable NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point;</span><br><span class="line"></span><br><span class="line">//UIView 的实例方法，可生成屏幕快照，要求iOS 7.0+</span><br><span class="line">- (nullable UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates;</span><br></pre></td></tr></table></figure>

<p>② <code>UIGestureRecognizerStateChanged</code> 时，移动cell。<br>通过手势在移动中，不断的回调，获取相应的位置，当手势移动到其他cell的位置时，就可以进行数据和视图的对调。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">//NSMutableArray 的实例方法，可快速交换数组中两个对象的位置</span><br><span class="line">- (void)exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2;</span><br><span class="line"></span><br><span class="line">//UITableView 的实例方法，可快速交换两个cell的位置，带动画</span><br><span class="line">- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath;</span><br><span class="line"></span><br><span class="line">//UITableView 的实例方法，可快速交换两个section的位置，带动画</span><br><span class="line">- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>③ <code>UIGestureRecognizerStateEnded</code> 时：放下cell，移除快照</p>
<br />

<p>完整的<code>longPress:</code>方法</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line">- (void)longPress:(UILongPressGestureRecognizer*)sender&#123;</span><br><span class="line">    UIGestureRecognizerState state = sender.state;</span><br><span class="line">    CGPoint location = [sender locationInView:_tableView];</span><br><span class="line">    switch (state) &#123;</span><br><span class="line">        case UIGestureRecognizerStateBegan:&#123;</span><br><span class="line">            NSLog(@&quot;选中cell&quot;);</span><br><span class="line">            _selectIndexPath = [_tableView indexPathForRowAtPoint:location];</span><br><span class="line">            if (!_selectIndexPath) return;</span><br><span class="line">            UITableViewCell* cell = [_tableView cellForRowAtIndexPath:_selectIndexPath];</span><br><span class="line">            _snapShot = [self snapshotViewAfterScreenUpdates:cell];</span><br><span class="line">            _snapShot.frame = CGRectMake(0, location.y, _snapShot.bounds.size.width, _snapShot.bounds.size.height);</span><br><span class="line">            [self.view addSubview:_snapShot];</span><br><span class="line">            cell.contentView.hidden = YES;</span><br><span class="line">        &#125;</span><br><span class="line">            break;</span><br><span class="line">        case UIGestureRecognizerStateChanged:&#123;</span><br><span class="line">            NSLog(@&quot;移动cell&quot;);</span><br><span class="line">            _snapShot.frame = CGRectMake(0, location.y, _snapShot.bounds.size.width, _snapShot.bounds.size.height);</span><br><span class="line">            NSIndexPath* changeIndexPath = [_tableView indexPathForRowAtPoint:location];</span><br><span class="line">            if (!_selectIndexPath || !changeIndexPath) return;</span><br><span class="line">            if (_selectIndexPath != changeIndexPath) &#123;</span><br><span class="line">                NSLog(@&quot;交换&quot;);</span><br><span class="line">                [self.lists exchangeObjectAtIndex:_selectIndexPath.row withObjectAtIndex:changeIndexPath.row];</span><br><span class="line">                //移动Section —— [self.tableView moveSection:0 toSection:0];</span><br><span class="line">                //移动row</span><br><span class="line">                [self.tableView moveRowAtIndexPath:_selectIndexPath toIndexPath:changeIndexPath];</span><br><span class="line">                UITableViewCell* selectCell = [_tableView cellForRowAtIndexPath:_selectIndexPath];</span><br><span class="line">                UITableViewCell* changeCell = [_tableView cellForRowAtIndexPath:changeIndexPath];</span><br><span class="line">                selectCell.contentView.hidden = NO;</span><br><span class="line">                changeCell.contentView.hidden = YES;</span><br><span class="line">                _selectIndexPath = changeIndexPath;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">            break;</span><br><span class="line">        case UIGestureRecognizerStateEnded:&#123;</span><br><span class="line">            NSLog(@&quot;放下cell&quot;);</span><br><span class="line">            [_snapShot removeFromSuperview];</span><br><span class="line">            _snapShot = nil;</span><br><span class="line">            if (!_selectIndexPath) return;</span><br><span class="line">            UITableViewCell* cell = [_tableView cellForRowAtIndexPath:_selectIndexPath];</span><br><span class="line">            cell.contentView.hidden = NO;</span><br><span class="line">            _selectIndexPath = nil;</span><br><span class="line">        &#125;</span><br><span class="line">            break;</span><br><span class="line">        default:</span><br><span class="line">            break;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://github.com/a334713698/DragSort">Demo</a></p>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/UITableView/" rel="tag">UITableView</a></li></ul>

    </footer>
  </div>

    
 
    
</article>

    
    <article
  id="post-自定义UITableView左滑删除样式"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2018/09/07/%E8%87%AA%E5%AE%9A%E4%B9%89UITableView%E5%B7%A6%E6%BB%91%E5%88%A0%E9%99%A4%E6%A0%B7%E5%BC%8F/"
    >自定义UITableView左滑删除样式</a> 
</h2>
 

      
    </header>
     
    <div class="article-meta">
      <a href="/2018/09/07/%E8%87%AA%E5%AE%9A%E4%B9%89UITableView%E5%B7%A6%E6%BB%91%E5%88%A0%E9%99%A4%E6%A0%B7%E5%BC%8F/" class="article-date">
  <time datetime="2018-09-07T08:57:59.000Z" itemprop="datePublished">2018-09-07</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/iOS/">iOS</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <p>最近在做番茄钟的项目，其中涉及到任务列表的界面，希望实现左滑删除的功能。UITableViewDelegate自带简单的左滑删除的接口，通过实现<code>canEditRowAtIndexPath方法</code>打开tableView可编辑的开关，再实现<code>editActionsForRowAtIndexPath方法</code>处理事件，<code>UITableViewRowAction</code>的实例允许修改文字和背景色。<br><img src="https://ws1.sinaimg.cn/large/0069RVTdgy1fv11c5vl0gj30lu05cdj5.jpg"></p>
<p>而我的需求是想把删除键做成一个垃圾桶图标。而系统没有直接可用的API，那就只能曲线救国了。</p>
<p>首先，这个删除按钮在 iOS11 和 iOS11以下的系统中，所处的父级是不一样的。</p>
<h2 id="在iOS11以前"><a href="#在iOS11以前" class="headerlink" title="在iOS11以前"></a>在iOS11以前</h2><p>删除按钮的父级是cell图。<br><img src="https://ws2.sinaimg.cn/large/0069RVTdgy1fv11nwlk64j319g0lc7fn.jpg"></p>
<h2 id="iOS11"><a href="#iOS11" class="headerlink" title="iOS11+"></a>iOS11+</h2><p>删除按钮的父级类名为<code>UISwipeActionPullView</code>，<code>UISwipeActionPullView</code>的父级为<code>UITableViewRowAction</code>，也就是说<code>UISwipeActionPullView</code>和cell是同级的。<br><img src="https://ws3.sinaimg.cn/large/0069RVTdgy1fv11nwb7dpj31ae0jkds6.jpg"></p>
<p>所以，两者需要以不同的方式实现。</p>
<p>在两种系统中，当还未左滑调出删除按钮时，输出cell或tableView的所有子视图，发现并没有删除按钮的存在。也就是说，他们是在需要的时候，被创建出来的。所以，我们需要重写某个方法去截获这个删除按钮。</p>
<h2 id="在iOS11以前-1"><a href="#在iOS11以前-1" class="headerlink" title="在iOS11以前"></a>在iOS11以前</h2><p>重写<code>insertSubview:atIndex</code>方法。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index &#123;</span><br><span class="line">    [super insertSubview:view atIndex:index];</span><br><span class="line">    DLog(@&quot;insertSubview&quot;);</span><br><span class="line">    if ([view isKindOfClass:NSClassFromString(@&quot;UITableViewCellDeleteConfirmationView&quot;)]) &#123;</span><br><span class="line">        for (UIButton *btn in view.subviews) &#123;</span><br><span class="line"></span><br><span class="line">            if ([btn isKindOfClass:[UIButton class]]) &#123;</span><br><span class="line">                [btn setBackgroundColor:[UIColor clearColor]];</span><br><span class="line">                [btn mas_updateConstraints:^(MASConstraintMaker *make) &#123;</span><br><span class="line">                    make.width.mas_equalTo(adaptWidth(35));</span><br><span class="line">                    make.height.mas_equalTo(adaptWidth(35));</span><br><span class="line">                    make.centerX.mas_equalTo(0);</span><br><span class="line">                    make.centerY.mas_equalTo(0);</span><br><span class="line">                &#125;];</span><br><span class="line"></span><br><span class="line">                [btn setTitle:nil forState:UIControlStateNormal];</span><br><span class="line">                UIImage *img = [IMAGE(@&quot;list_deleting&quot;) imageForThemeColor:[UIColor redColor]];</span><br><span class="line">                [btn setImage:img forState:UIControlStateNormal];</span><br><span class="line">                [btn setImage:img forState:UIControlStateHighlighted];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="iOS11-1"><a href="#iOS11-1" class="headerlink" title="iOS11+"></a>iOS11+</h2><p>新建并使用一个继承于UITableView的控件，重写<code>layoutSubviews</code>方法。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">- (void)layoutSubviews&#123;</span><br><span class="line">    [super layoutSubviews];</span><br><span class="line"></span><br><span class="line">    //iOS11版本以上,自定义删除按钮:</span><br><span class="line">    if ([[[UIDevice currentDevice] systemVersion] doubleValue] &gt;= 11.0) &#123;</span><br><span class="line">        for (UIView *subview in self.subviews)</span><br><span class="line">        &#123;</span><br><span class="line">            if([subview isKindOfClass:NSClassFromString(@&quot;UISwipeActionPullView&quot;)])</span><br><span class="line">            &#123;</span><br><span class="line">                UIView *swipeActionPullView = subview;</span><br><span class="line">                swipeActionPullView.backgroundColor =  [UIColor clearColor];</span><br><span class="line"></span><br><span class="line">                UIButton *swipeActionStandardBtn = subview.subviews[0];</span><br><span class="line">                if ([swipeActionStandardBtn isKindOfClass:NSClassFromString(@&quot;UISwipeActionStandardButton&quot;)]) &#123;</span><br><span class="line"></span><br><span class="line">                    [swipeActionStandardBtn mas_updateConstraints:^(MASConstraintMaker *make) &#123;</span><br><span class="line">                        make.width.mas_equalTo(adaptWidth(35));</span><br><span class="line">                        make.height.mas_equalTo(adaptWidth(35));</span><br><span class="line">                        make.left.mas_equalTo(0);</span><br><span class="line">                        make.centerY.mas_equalTo(0);</span><br><span class="line">                    &#125;];</span><br><span class="line">                    [swipeActionStandardBtn setTitle:nil forState:UIControlStateNormal];</span><br><span class="line">                    [swipeActionStandardBtn setImage:[IMAGE(@&quot;list_deleting&quot;) imageForThemeColor:[UIColor redColor]] forState:UIControlStateNormal];</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>*在iOS11以前，左滑cell不会走<code>layoutSubviews</code>的方法。在iOS11上，左滑时tableView不会走<code>insertSubview:atIndex</code>方法。</p>
<p><img src="https://ws2.sinaimg.cn/large/0069RVTdgy1fv12w0xbwqj30lm05gade.jpg"></p>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/UITableView/" rel="tag">UITableView</a></li></ul>

    </footer>
  </div>

    
 
    
</article>

    
    <article
  id="post-Diary"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2018/09/05/Diary/"
    >Diary</a> 
</h2>
 

      
    </header>
     
    <div class="article-meta">
      <a href="/2018/09/05/Diary/" class="article-date">
  <time datetime="2018-09-05T06:28:00.000Z" itemprop="datePublished">2018-09-05</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/%E9%9A%8F%E8%AE%B0/">随记</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <h3 id="2018年9月5日-周三"><a href="#2018年9月5日-周三" class="headerlink" title="2018年9月5日 周三"></a>2018年9月5日 周三</h3><hr>
<p>今天尝试着将小程序上传提交审核了。<br>从8月8日创建项目开始，历时将近一个月时间，算是做了点东西出来。<br>一个产品在设计伊始应该先有个原型，但是我不是产品经理，所以我就用Page画了一些简单的图形，来提现界面的雏形。<br>然后…然后就直接上手开发了。<br>可发过程中也遇到了很多问题，例如如何获取小程序的全局变量，如何去适配屏幕的高宽，单位的使用，是用px，还是rpx，等等，等等<br>不过好在，所有这些问题，在搜索引擎的帮助下基本都能解决。<br>对JS的感觉是，既陌生又熟悉，因为同时在学习Swift的缘故，发现二者还是有一些相似之处。<br>HTML和CSS是上大学那会儿学的，写的时候，还是不得不时不时查阅文档才能达到想要的效果。<br>最近，腾讯还上线了云开发，但是目前还在公测阶段，需要申请公测资格，我填写了好几次信息，都没有收到允许公测的邮件..<br>所有后面直接用了Bomb的后台云。<br>Bomb后端云的免费版每月有10万次的API调用额度，20GB的存储空间，20GB的流量，以及30条短信。<br>如果用完了或者不够用，也可以按需充值。还是蛮方便的<br>这个小项目下做来，有些感慨，在做事情之前，还是应该有相对充分的准备。<br>对于不熟悉的语言，按需学习做项目的方式，会让人特别难受，特别是前期，还处于摸索的阶段，基本上是五行代码一小查，十行代码一大查的状态。<br>小程序的页面花了大概三周的时间，每天基本只用半天的时间去写（下午学习Swift），9个页面，包括信息的展示页面，和信息的发布界面，以及个人中心页面，最后只用来两个信息展示页面…内容的展示姑且先用CVS记录，再导入数据库进行管理。是骡子是马，先拉出去溜溜看吧。<br>估计在小程序上线过程中，还会遇到一些问题，不知道会不会因为功能过于简单，直接不让上了…<br><br/></p>
<h3 id="2018年9月2日-周一"><a href="#2018年9月2日-周一" class="headerlink" title="2018年9月2日 周一"></a>2018年9月2日 周一</h3><hr>
<p>使用Bomb作为小程序的后端，在线编辑数据库，亦可导入cvs的文件，非常方便使用。<br>不需要自己写后端代码，甚至连服务器都不需要部署跟购买，在满足需求的程度上够用了。</p>
<br/>

<h3 id="2018年2月11日-周日"><a href="#2018年2月11日-周日" class="headerlink" title="2018年2月11日 周日"></a>2018年2月11日 周日</h3><hr>
<p>添加了Livere评论控件，从此以后文章可以被评论了：）</p>
<br/>

<h3 id="2018年2月9日-周五"><a href="#2018年2月9日-周五" class="headerlink" title="2018年2月9日 周五"></a>2018年2月9日 周五</h3><hr>
<p>发现博客首页的_content内容摘要部分部分，无法点击进入文章详情。今天就在archer主题的文件里做了个小改动，实现内容的点击事件<br>实现方法也非常简单。首先需要找到首页的布局文件,其文件目录大概是：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/blogRootDir/themes/archer/layout/index.ejs</span><br></pre></td></tr></table></figure>
<p>使用文档编辑器打开<code>index.ejs</code>文件，找到以下内容：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;abstract-content&quot;</span>&gt;</span></span><br><span class="line">    &lt;%- _content %&gt;</span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>改成如下代码，就搞定了：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">&quot;abstract-title&quot;</span> <span class="attr">href</span> = <span class="string">&quot;&lt;%- url_for(_post.path) %&gt;&quot;</span> &gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;abstract-content&quot;</span>&gt;</span></span><br><span class="line">        &lt;%- _content %&gt;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure>

<br/>

<h3 id="2018年2月8日-周四"><a href="#2018年2月8日-周四" class="headerlink" title="2018年2月8日 周四"></a>2018年2月8日 周四</h3><hr>
<p>今天写下第一篇，和技术有一点点关系的博客。虽然大部分内容是通过粘贴和借鉴的。不过在排版和Markdown的语法上，还是得到了学习。<br>想对自己说，再接再厉吧。<br>以后想通过Diary这个页面，记录自己生活和学习的点滴，希望在未来的某一天，能看到自己逐步地成长。</p>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Diary/" rel="tag">Diary</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Life/" rel="tag">Life</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/%E6%88%90%E9%95%BF/" rel="tag">成长</a></li></ul>

    </footer>
  </div>

    
 
    
</article>

    
    <article
  id="post-使用Xcode的Instruments-Leaks-监测App的内存泄漏问题"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2018/06/20/%E4%BD%BF%E7%94%A8Xcode%E7%9A%84Instruments-Leaks-%E7%9B%91%E6%B5%8BApp%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E9%97%AE%E9%A2%98/"
    >使用Xcode的Instruments(Leaks)监测App的内存泄漏问题</a> 
</h2>
 

      
    </header>
     
    <div class="article-meta">
      <a href="/2018/06/20/%E4%BD%BF%E7%94%A8Xcode%E7%9A%84Instruments-Leaks-%E7%9B%91%E6%B5%8BApp%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E9%97%AE%E9%A2%98/" class="article-date">
  <time datetime="2018-06-20T08:58:13.000Z" itemprop="datePublished">2018-06-20</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/iOS/">iOS</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <p>最近项目提交App Store审核，有些闲暇时间，打算用Instruments工具里的Leaks<br>检查一下项目中存在的内存泄漏问题。</p>
<h4 id="一、准备工作"><a href="#一、准备工作" class="headerlink" title="一、准备工作"></a>一、准备工作</h4><h5 id="1-edit-scheme"><a href="#1-edit-scheme" class="headerlink" title="1.edit scheme"></a>1.edit scheme</h5><p>修改为测试环境<br><img src="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/%E7%9B%91%E6%B5%8BApp%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/0.edit-scheme.png"><br>将Profile中的Build Configuration选为Debug<br><img src="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/%E7%9B%91%E6%B5%8BApp%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/0.profile-debug.png"></p>
<h5 id="2-Debug-Information-Format"><a href="#2-Debug-Information-Format" class="headerlink" title="2.Debug Information Format"></a>2.Debug Information Format</h5><p>设置调试运行的时候生成 dSYM文件（用于代码定位）</p>
<p><code>Build Settings --&gt; Debug Information Format</code></p>
<p><img src="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/%E7%9B%91%E6%B5%8BApp%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/0.debug-information-format.jpg"></p>
<h4 id="二、开始监测"><a href="#二、开始监测" class="headerlink" title="二、开始监测"></a>二、开始监测</h4><h5 id="1-打开Instruments"><a href="#1-打开Instruments" class="headerlink" title="1.打开Instruments"></a>1.打开Instruments</h5><p>在Xcode的导航栏中找到Instruments。</p>
<p><code>Xcode --&gt; Open Developer Tool --&gt; Instruments</code></p>
<p><img src="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/%E7%9B%91%E6%B5%8BApp%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/1%E6%89%BE%E5%88%B0instruments.png"></p>
<h5 id="2-双击选择Leaks"><a href="#2-双击选择Leaks" class="headerlink" title="2.双击选择Leaks"></a>2.双击选择Leaks</h5><p><img src="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/%E7%9B%91%E6%B5%8BApp%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/2%E9%80%89%E6%8B%A9leaks.png"></p>
<h5 id="3-选择设备和项目"><a href="#3-选择设备和项目" class="headerlink" title="3.选择设备和项目"></a>3.选择设备和项目</h5><p>找到运行的设备和正在运行的项目。</p>
<p>选好设备和项目，点击左侧的大红点，项目会在对应的设备中重新运行一次。并做好监测准备<br><img src="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/%E7%9B%91%E6%B5%8BApp%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/3%E9%80%89%E6%8B%A9%E8%AE%BE%E5%A4%87%E4%BB%A5%E5%8F%8A%E9%A1%B9%E7%9B%AE.png"></p>
<h5 id="4-内存监测"><a href="#4-内存监测" class="headerlink" title="4.内存监测"></a>4.内存监测</h5><p>由于Leaks是动态监测，所以需要一边手动操作App，一边观察Leaks界面上的变化。当出现红色叉叉时，说明出现了内存泄漏，可以暂停进程，进行查看<br><img src="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/%E7%9B%91%E6%B5%8BApp%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/4.%E5%8F%91%E7%8E%B0%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%EF%BC%8C%E5%B9%B6%E6%9A%82%E5%81%9C%E8%BF%9B%E7%A8%8B.png"></p>
<p>5.定位内存泄漏的位置<br>选择 <code>Leaks ——&gt; Call Tree</code>，最底下会出现4个选框<br><img src="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/%E7%9B%91%E6%B5%8BApp%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/6%E9%80%89%E6%8B%A9calltree.png"></p>
<p>5.1 点击第二个<code>Call Tree</code>，勾选 <code>Invert Call Tree</code> 和 <code>Hide System Libraries</code></p>
<p><strong>勾选前</strong><br>![](<a target="_blank" rel="noopener" href="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/%E7%9B%91%E6%B5%8BApp%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/7.call">https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/监测App的内存泄漏/7.call</a> tree不选之前的对比图.png)</p>
<p><strong>勾选后</strong><br>![](<a target="_blank" rel="noopener" href="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/%E7%9B%91%E6%B5%8BApp%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/7.call">https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/监测App的内存泄漏/7.call</a> tree 选项.png)</p>
<h5 id="6-确认位置，修改代码"><a href="#6-确认位置，修改代码" class="headerlink" title="6.确认位置，修改代码"></a>6.确认位置，修改代码</h5><p>此时显示的就是若干条内存泄漏的代码部分，选择其中一条双击，即可显示代码。还可直接跳转到代码在Xcode中额具体位置<br><img src="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/%E7%9B%91%E6%B5%8BApp%E7%9A%84%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/8%E8%B7%B3%E8%BD%AC.png"></p>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Instruments/" rel="tag">Instruments</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Leaks/" rel="tag">Leaks</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Xcode/" rel="tag">Xcode</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/" rel="tag">内存泄漏</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/%E8%B0%83%E8%AF%95%E4%BC%98%E5%8C%96/" rel="tag">调试优化</a></li></ul>

    </footer>
  </div>

    
 
    
</article>

    
    <article
  id="post-多线程的理解——队列与执行方式"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2018/03/03/%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%9A%84%E7%90%86%E8%A7%A3%E2%80%94%E2%80%94%E9%98%9F%E5%88%97%E4%B8%8E%E6%89%A7%E8%A1%8C%E6%96%B9%E5%BC%8F/"
    >多线程的理解——队列与执行方式</a> 
</h2>
 

      
    </header>
     
    <div class="article-meta">
      <a href="/2018/03/03/%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%9A%84%E7%90%86%E8%A7%A3%E2%80%94%E2%80%94%E9%98%9F%E5%88%97%E4%B8%8E%E6%89%A7%E8%A1%8C%E6%96%B9%E5%BC%8F/" class="article-date">
  <time datetime="2018-03-03T03:01:06.000Z" itemprop="datePublished">2018-03-03</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/iOS/">iOS</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <p>多线程的理解——队列与执行方式</p>
<h4 id="1-队列类型"><a href="#1-队列类型" class="headerlink" title="1.队列类型"></a>1.队列类型</h4><ul>
<li>串行队列：顺序执行，一次执行一个任务。依次从队列中取出一个任务执行，必须一个任务执行完了，才能从队列里面取出下一个任务。</li>
<li>并行队列：任务是按照加入到队列中的顺序开始执行，但任务完成时的顺序是不确定的。</li>
<li>主队列：主线程中的串行队列（系统默认创建）。</li>
<li>全局队列：是全局的并行队列（系统默认创建。几乎等效于并行队列）。<br/></li>
</ul>
<h4 id="2-执行方式"><a href="#2-执行方式" class="headerlink" title="2.执行方式"></a>2.执行方式</h4><ul>
<li>同步执行sync：不开新线程</li>
<li>异步执行async：开辟新线程<br/></li>
</ul>
<h4 id="3-队列与执行方式"><a href="#3-队列与执行方式" class="headerlink" title="3.队列与执行方式"></a>3.队列与执行方式</h4><ul>
<li>串行队列同步执行：不开线程，在原来线程里面一个一个顺序执行</li>
<li>串行队列异步执行：开一条线程，在这个新线程里面一个一个顺序执行</li>
<li>并行队列同步执行：不开线程，在原来线程里面执行</li>
<li>并行队列异步执行：开多个线程，并发执行（不一定是一个一个）执行<br><img src="https://ws2.sinaimg.cn/large/006tNc79gy1fozfz2vff0j313o0c8dm6.jpg"><br/></li>
</ul>
<h4 id="4-死锁问题"><a href="#4-死锁问题" class="headerlink" title="4.死锁问题"></a>4.死锁问题</h4><p>死锁问题的理解，可参考：<a target="_blank" rel="noopener" href="https://www.jianshu.com/p/bd574fd21da5">《为什么dispatch_sync在主线程会死锁》</a></p>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" rel="tag">多线程</a></li></ul>

    </footer>
  </div>

    
 
    
</article>

    
    <article
  id="post-Mac上搭建基于GitHub的Hexo博客"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2018/02/08/Mac%E4%B8%8A%E6%90%AD%E5%BB%BA%E5%9F%BA%E4%BA%8EGitHub%E7%9A%84Hexo%E5%8D%9A%E5%AE%A2/"
    >Mac上搭建基于GitHub的Hexo博客</a> 
</h2>
 

      
    </header>
     
    <div class="article-meta">
      <a href="/2018/02/08/Mac%E4%B8%8A%E6%90%AD%E5%BB%BA%E5%9F%BA%E4%BA%8EGitHub%E7%9A%84Hexo%E5%8D%9A%E5%AE%A2/" class="article-date">
  <time datetime="2018-02-08T06:32:18.000Z" itemprop="datePublished">2018-02-08</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/%E5%8D%9A%E5%AE%A2/">博客</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <p>2017农历的最后几天，项目都完成得差不多了。想着建立一个自己的博客，花了两天时间，在网上搜索各种资料，总算是把个人博客建起来了。过程就是不断试错，是在进行不下去了，就推翻重来。本人是一枚iOS coder，工作机是一台Mac，所以就讲讲在macOS系统上如何基于<a target="_blank" rel="noopener" href="https://hexo.io/zh-cn/">Hexo</a>+<a target="_blank" rel="noopener" href="https://github.com/">Github</a>创建个人博客。文章开始前，需要提醒一下，文中出现的<code>$</code>符号，在终端中都是不需要输入或粘贴的。</p>
<h2 id="环境配置"><a href="#环境配置" class="headerlink" title="环境配置"></a>环境配置</h2><h3 id="Node-js"><a href="#Node-js" class="headerlink" title="Node.js"></a>Node.js</h3><p>用来生成静态页面。可直接在<a target="_blank" rel="noopener" href="https://nodejs.org/en/">Node.js官网</a>，下载镜像安装。</p>
<h3 id="Git"><a href="#Git" class="headerlink" title="Git"></a>Git</h3><p>用来提交本地的Hexo内容到Github上。<br>电脑上如果已经装了Xcode，可不比进行本步骤，因为Xcode自带git。<br>如果没有Xcode，可以使用 <a target="_blank" rel="noopener" href="https://brew.sh/">Homebrew</a>, <a target="_blank" rel="noopener" href="https://www.macports.org/">MacPorts</a> ：brew install git;或下载 <a target="_blank" rel="noopener" href="https://sourceforge.net/projects/git-osx-installer/">安装程序</a> 安装<br>如果不是iOS开发者，其实真的没必要为了建站下一个好几G的Xcode</p>
<h2 id="安装Hexo"><a href="#安装Hexo" class="headerlink" title="安装Hexo"></a>安装Hexo</h2><p>所有必备的应用程序安装完成后，即可使用 npm 安装 Hexo。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> npm install -g hexo-cli</span></span><br></pre></td></tr></table></figure>
<p>这里如果报错，可以尝试sudo命令。输入管理员密码（Mac登录密码）即开始安装。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> sudo npm install -g hexo-cli</span></span><br></pre></td></tr></table></figure>

<h2 id="初始化"><a href="#初始化" class="headerlink" title="初始化"></a>初始化</h2><p>终端cd到一个你选定的目录（Mac支持直接将文件或文件夹拖入终端，直接显示路径），然后执行<code>hexo init</code>命令</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> hexo init blogName</span></span><br></pre></td></tr></table></figure>
<p>这里需要提一下，如果需要把博客的根目录文件夹建在桌面上：cd到桌面，然后执行<code>hexo init blogName</code>命令即可。系统会创建blogName这个目录在桌面上。<br>下一步，cd到<code>blogName</code>，执行安装命令</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> npm install</span></span><br></pre></td></tr></table></figure>

<p>安装完毕后，指定文件夹的目录如下</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── _config.yml</span><br><span class="line">├── package.json</span><br><span class="line">├── scaffolds</span><br><span class="line">├── source</span><br><span class="line">|   ├── _drafts</span><br><span class="line">|   └── _posts</span><br><span class="line">└── themes</span><br></pre></td></tr></table></figure>
<p>此时，可开启hexo服务器</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> hexo server</span></span><br><span class="line">简写：</span><br><span class="line"><span class="meta">$</span><span class="bash"> hexo s</span></span><br></pre></td></tr></table></figure>
<p>服务器成功开启。系统会提示</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">INFO  Start processing</span><br><span class="line">INFO  Hexo is running at http://localhost:4000/. Press Ctrl+C to stop.</span><br></pre></td></tr></table></figure>
<p>此时，在可以在浏览器中输入<code>http://localhost:4000/</code> 或 <code>127.0.0.1:4000</code> ，如果出现了下图页面，就说明已获得“阶段性”的成功。<br><img src="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/Hexo/hexo-page.png/" alt="img"></p>
<h2 id="关联Github"><a href="#关联Github" class="headerlink" title="关联Github"></a>关联Github</h2><h3 id="新建仓库"><a href="#新建仓库" class="headerlink" title="新建仓库"></a>新建仓库</h3><p>在自己的GitHub账户上创建一个新的仓库（repository）<br>命名规则为：<code>你的用户名.github.io</code>，如<code>a334713698.github.io</code></p>
<h3 id="配置文件"><a href="#配置文件" class="headerlink" title="配置文件"></a>配置文件</h3><p>在blogName文件中，找到名为<code>_config.yml</code>的文件，使用任意文本编辑器打开此文件。<br>找到如下代码：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># Deployment</span><br><span class="line">## Docs: https://hexo.io/docs/deployment.html</span><br><span class="line">deploy:</span><br><span class="line">  type:</span><br></pre></td></tr></table></figure>
<p>可通过键盘<code>command+F</code>，调起编辑器的搜索功能，查找“deploy”字段<br>并将内容填充为：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">deploy:</span><br><span class="line">  type: git</span><br><span class="line">  repository: https://github.com/a334713698/a334713698.github.io.git</span><br></pre></td></tr></table></figure>
<p>注意：<code>repository:</code>后填写的应该是自己的创建的仓库地址。</p>
<h3 id="生成静态页面"><a href="#生成静态页面" class="headerlink" title="生成静态页面"></a>生成静态页面</h3><p>此时应保证自己在blogName根目录下。如果不在指定目录，在终端上输入cd ，再直接将指定文件夹拖进终端，即可获取文件夹路径，按下回车，进入指定目录下。<br>接着执行<code>generate</code>命令：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> hexo generate</span></span><br><span class="line">简写：</span><br><span class="line"><span class="meta">$</span><span class="bash"> hexo g</span></span><br></pre></td></tr></table></figure>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">若出现如下报错：</span><br><span class="line">ERROR Local hexo not found in ~/blog</span><br><span class="line">ERROR Try runing: &#x27;npm install hexo --save&#x27;</span><br><span class="line"></span><br><span class="line">则执行命令：</span><br><span class="line">$ npm install hexo --save</span><br><span class="line"></span><br><span class="line">若无报错，自行忽略此步骤。</span><br></pre></td></tr></table></figure>

<h3 id="部署网页到git上"><a href="#部署网页到git上" class="headerlink" title="部署网页到git上"></a>部署网页到git上</h3><p>执行部署的命令</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> hexo deploy</span></span><br><span class="line">简写：</span><br><span class="line"><span class="meta">$</span><span class="bash"> hexo d</span></span><br></pre></td></tr></table></figure>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">若执行命令hexo deploy仍然报错：</span><br><span class="line">无法连接git或找不到git</span><br><span class="line"></span><br><span class="line">则执行命令：</span><br><span class="line">$ npm install hexo-deployer-git --save  </span><br><span class="line"></span><br><span class="line">然后再次执行</span><br><span class="line">$ hexo generate //生成静态页面</span><br><span class="line">$ hexo deploy   //部署到git</span><br><span class="line"></span><br><span class="line">tip：静态页面生成和部署两个步骤可以合并写成：</span><br><span class="line">$ hexo g -d</span><br></pre></td></tr></table></figure>
<p>若未关联过Github，则执行hexo deploy命令时终端会提示你输入Github的用户名和密码，正确填写GitHub的账号密码即可。<br><code>hexo deploy</code>部署成功后，浏览器中打开网址 <a target="_blank" rel="noopener" href="http://a334713698.github.io/">http://a334713698.github.io</a> （将a334713698换成自己的用户名）也能看到博客的主页。</p>
<h3 id="添加ssh-key到Github"><a href="#添加ssh-key到Github" class="headerlink" title="添加ssh key到Github"></a>添加ssh key到Github</h3><h4 id="检查SSH-keys是否存在Github"><a href="#检查SSH-keys是否存在Github" class="headerlink" title="检查SSH keys是否存在Github"></a>检查SSH keys是否存在Github</h4><p>执行如下命令，检查SSH keys是否存在。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> ls -al ~/.ssh</span></span><br></pre></td></tr></table></figure>
<p>如果有文件<code>id_rsa.pub</code> 或 <code>id_dsa.pub</code>，则直接进入<code>将SSH key添加到Github中</code>的步骤，否则进入下一步生成SSH key。</p>
<h4 id="生成新的ssh-key"><a href="#生成新的ssh-key" class="headerlink" title="生成新的ssh key"></a>生成新的ssh key</h4><p>执行如下命令生成public/private rsa key pair，注意将<a href="mailto:&#x79;&#x6f;&#x75;&#114;&#95;&#x65;&#109;&#97;&#x69;&#108;&#64;&#101;&#x78;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#x6d;">&#x79;&#x6f;&#x75;&#114;&#95;&#x65;&#109;&#97;&#x69;&#108;&#64;&#101;&#x78;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#x6d;</a>换成你自己注册Github的邮箱地址。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> ssh-keygen -t rsa -C <span class="string">&quot;your_email@example.com&quot;</span></span></span><br></pre></td></tr></table></figure>
<p>默认会在相应路径下（~/.ssh/id_rsa.pub）生成id_rsa和id_rsa.pub两个文件。</p>
<h4 id="将ssh-key添加到Github中"><a href="#将ssh-key添加到Github中" class="headerlink" title="将ssh key添加到Github中"></a>将ssh key添加到Github中</h4><p>Finder（访达）前往<code>~/.ssh/id_rsa.pub</code>打开id_rsa.pub文件，里面的信息即为SSH key，将这些信息复制到Github的Add SSH key页面即可。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">进入Github –&gt; Settings –&gt; SSH and GPG keys –&gt; add SSH key</span><br></pre></td></tr></table></figure>
<p>Title任意填（也可不填，我就没填），粘贴内容要从头部的<code>ssh-rsa</code>开始粘，将复制的内容粘贴到Key里，点击下方<code>Add key</code>完成设置。</p>
<h2 id="结尾"><a href="#结尾" class="headerlink" title="结尾"></a>结尾</h2><p>到这里，建站工作基本搞定。接下去，就可以发布文章，更换主题了。<br>本文大部分内容都参考于<a target="_blank" rel="noopener" href="http://gonghonglou.com/">与佳期的个人博客</a> 的 <a target="_blank" rel="noopener" href="http://gonghonglou.com/2016/02/03/firstblog/">《Mac上搭建基于GitHub的Hexo博客<br>述》</a>一文。文中还涉及文章发布，域名绑定，主题更换等内容，都非常有帮助。</p>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Tech/" rel="tag">Tech</a></li></ul>

    </footer>
  </div>

    
 
    
</article>

    
    <article
  id="post-第一篇文章"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h2 itemprop="name">
  <a class="article-title" href="/2018/02/07/%E7%AC%AC%E4%B8%80%E7%AF%87%E6%96%87%E7%AB%A0/"
    >第一篇文章</a> 
</h2>
 

      
    </header>
     
    <div class="article-meta">
      <a href="/2018/02/07/%E7%AC%AC%E4%B8%80%E7%AF%87%E6%96%87%E7%AB%A0/" class="article-date">
  <time datetime="2018-02-07T08:19:21.000Z" itemprop="datePublished">2018-02-07</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/%E9%9A%8F%E7%AC%94/">随笔</a>
  </div>
   
    </div>
      
    <div class="article-entry" itemprop="articleBody">
       
  <p>捯饬了两天，终于把博客弄起来了，随便写点儿什么吧..<br>通过看<a target="_blank" rel="noopener" href="https://hexo.io/zh-cn/">Hexo官网</a>的文档，初步了解了Hexo建站的方式和一些常用的命令行<br>另外参考了两名博主的文章，对本次建站都非常地有帮助，分别是：<a target="_blank" rel="noopener" href="http://tengj.top/tags/hexo/">嘟嘟独立博客</a>、<a target="_blank" rel="noopener" href="http://gonghonglou.com/2016/02/03/firstblog/">与佳期的个人博客</a><br>使用的theme来自Yilia (<a target="_blank" rel="noopener" href="https://github.com/litten/hexo-theme-yilia">hexo-theme-yilia</a>)可直接点击括号里的链接，前往主题所存的Github页面  </p>
<p>2018年2月8日<br>更换主题：来自Wee(<a target="_blank" rel="noopener" href="https://github.com/fi3ework/hexo-theme-archer">hexo-theme-archer</a>)  </p>
<p>创建博客的初衷：  </p>
<ul>
<li>博客的存在，能够表达自己的情感；</li>
<li>书写技术文章，督促自己对技术知识点的归纳、总结和理解；</li>
<li>自主建站，非常酷。这也是当初选择编程这项实业的原因。</li>
</ul>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <footer class="article-footer">
       
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Life/" rel="tag">Life</a></li></ul>

    </footer>
  </div>

    
 
    
</article>

    
  </article>
  

  
  <nav class="page-nav">
    
    <a class="extend prev" rel="prev" href="/page/2/">上一页</a><a class="page-number" href="/">1</a><a class="page-number" href="/page/2/">2</a><span class="page-number current">3</span>
  </nav>
  
</section>
</div>

      <footer class="footer">
  <div class="outer">
    <ul>
      <li>
        Copyrights &copy;
        2018-2022
        <i class="ri-heart-fill heart_icon"></i> GG266
      </li>
    </ul>
    <ul>
      <li>
        
      </li>
    </ul>
    <ul>
      <li>
        
        
        <span>
  <span><i class="ri-user-3-fill"></i>访问人数:<span id="busuanzi_value_site_uv"></span></span>
  <span class="division">|</span>
  <span><i class="ri-eye-fill"></i>浏览次数:<span id="busuanzi_value_page_pv"></span></span>
</span>
        
      </li>
    </ul>
    <ul>
      
    </ul>
    <ul>
      
      <li>
          <img src="/images/beian.png"></img>
          <a href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=33010902002204" target="_black" rel="nofollow">浙公网安备 33010902002204号</a>
      </li>
        
    </ul>
    <ul>
      <li>
        <!-- cnzz统计 -->
        
        <script type="text/javascript" src='https://s4.cnzz.com/z_stat.php?id=1280804963&amp;web_id=1280804963'></script>
        
      </li>
    </ul>
  </div>
</footer>    
    </main>
    <div class="float_btns">
      <div class="totop" id="totop">
  <i class="ri-arrow-up-line"></i>
</div>

<div class="todark" id="todark">
  <i class="ri-moon-line"></i>
</div>

    </div>
    <aside class="sidebar on">
      <button class="navbar-toggle"></button>
<nav class="navbar">
  
  <div class="logo">
    <a href="/"><img src="/images/ayer-side.svg" alt="DJ Hong&#39;s BLOG"></a>
  </div>
  
  <ul class="nav nav-main">
    
    <li class="nav-item">
      <a class="nav-item-link" href="/">主页</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/archives">归档</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/categories">分类</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/tags">标签</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/about">关于</a>
    </li>
    
  </ul>
</nav>
<nav class="navbar navbar-bottom">
  <ul class="nav">
    <li class="nav-item">
      
      
      <a class="nav-item-link" target="_blank" href="/atom.xml" title="RSS Feed">
        <i class="ri-rss-line"></i>
      </a>
      
    </li>
  </ul>
</nav>
<div class="search-form-wrap">
  <div class="local-search local-search-plugin">
  <input type="search" id="local-search-input" class="local-search-input" placeholder="Search...">
  <div id="local-search-result" class="local-search-result"></div>
</div>
</div>
    </aside>
    <div id="mask"></div>

<!-- #reward -->
<div id="reward">
  <span class="close"><i class="ri-close-line"></i></span>
  <p class="reward-p"><i class="ri-cup-line"></i>请我喝杯咖啡吧~</p>
  <div class="reward-box">
    
    <div class="reward-item">
      <img class="reward-img" src="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/alipay.JPG">
      <span class="reward-type">支付宝</span>
    </div>
    
    
    <div class="reward-item">
      <img class="reward-img" src="https://gitee.com/hongdongjie/gg266picgo/raw/master/pic4blog/wechat.JPG">
      <span class="reward-type">微信</span>
    </div>
    
  </div>
</div>
    
<script src="/js/jquery-3.6.0.min.js"></script>
 
<script src="/js/lazyload.min.js"></script>

<!-- Tocbot -->

<script src="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.js"></script>
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.css"
/>
<script src="https://cdn.jsdelivr.net/npm/justifiedGallery@3.7.0/dist/js/jquery.justifiedGallery.min.js"></script>

<script src="/dist/main.js"></script>

<!-- ImageViewer -->
 <!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">

    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>

    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">

        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>

        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">

            <div class="pswp__top-bar">

                <!--  Controls are self-explanatory. Order can be changed. -->

                <div class="pswp__counter"></div>

                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>

                <button class="pswp__button pswp__button--share" style="display:none" title="Share"></button>

                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>

                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>

                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                        <div class="pswp__preloader__cut">
                            <div class="pswp__preloader__donut"></div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div>
            </div>

            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>

            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>

            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>

        </div>

    </div>

</div>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.min.css">
<script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js"></script>

<script>
    function viewer_init() {
        let pswpElement = document.querySelectorAll('.pswp')[0];
        let $imgArr = document.querySelectorAll(('.article-entry img:not(.reward-img)'))

        $imgArr.forEach(($em, i) => {
            $em.onclick = () => {
                // slider展开状态
                // todo: 这样不好，后面改成状态
                if (document.querySelector('.left-col.show')) return
                let items = []
                $imgArr.forEach(($em2, i2) => {
                    let img = $em2.getAttribute('data-idx', i2)
                    let src = $em2.getAttribute('data-target') || $em2.getAttribute('src')
                    let title = $em2.getAttribute('alt')
                    // 获得原图尺寸
                    const image = new Image()
                    image.src = src
                    items.push({
                        src: src,
                        w: image.width || $em2.width,
                        h: image.height || $em2.height,
                        title: title
                    })
                })
                var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, {
                    index: parseInt(i)
                });
                gallery.init()
            }
        })
    }
    viewer_init()
</script> 
<!-- MathJax -->

<!-- Katex -->

<!-- busuanzi  -->
 
<script src="/js/busuanzi-2.3.pure.min.js"></script>
 
<!-- ClickLove -->

<!-- ClickBoom1 -->

<!-- ClickBoom2 -->

<!-- CodeCopy -->
 
<link rel="stylesheet" href="/css/clipboard.css">
 <script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script>
  function wait(callback, seconds) {
    var timelag = null;
    timelag = window.setTimeout(callback, seconds);
  }
  !function (e, t, a) {
    var initCopyCode = function(){
      var copyHtml = '';
      copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
      copyHtml += '<i class="ri-file-copy-2-line"></i><span>COPY</span>';
      copyHtml += '</button>';
      $(".highlight .code pre").before(copyHtml);
      $(".article pre code").before(copyHtml);
      var clipboard = new ClipboardJS('.btn-copy', {
        target: function(trigger) {
          return trigger.nextElementSibling;
        }
      });
      clipboard.on('success', function(e) {
        let $btn = $(e.trigger);
        $btn.addClass('copied');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-checkbox-circle-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPIED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-checkbox-circle-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
      clipboard.on('error', function(e) {
        e.clearSelection();
        let $btn = $(e.trigger);
        $btn.addClass('copy-failed');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-time-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPY FAILED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-time-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
    }
    initCopyCode();
  }(window, document);
</script>
 
<!-- CanvasBackground -->

<script>
  if (window.mermaid) {
    mermaid.initialize({ theme: "forest" });
  }
</script>


    
    <div id="music">
    
    
    
    <iframe frameborder="no" border="1" marginwidth="0" marginheight="0" width="200" height="52"
        src="//music.163.com/outchain/player?type=2&id=1908797593&auto=1&height=32"></iframe>
</div>

<style>
    #music {
        position: fixed;
        right: 15px;
        bottom: 0;
        z-index: 998;
    }
</style>
    
    

  </div>
</body>

</html>